﻿
using Boilen.Primitives.Members;
using System.Collections.Generic;


namespace Boilen.Primitives.Implementers {

    /// <inheritdoc/>
    /// <summary>
    /// Implements a new dependency property.
    /// </summary>
    public sealed class NewDependencyProperty<T> : DependencyProperty<T> {

        /// <inheritdoc/>
        protected override IEnumerable<InitializationMember> Initializers {
            get {
                // Add constructor initializer for dependency property default values, as needed.
                foreach( var pair in this.DefaultValues )
                    if( this.InitializeDefaultValueInConstructor( pair.Value ) )
                        yield return new InitializationMember( this.AccessorName, pair.Value ) { Condition = pair.Key };

                // Add static initializers for dependency property fields.
                string initializerScope = this.Parent.TypeNamePrefix;

                var wpfArgs = this.BuildRegistrationArguments( false );
                var wpfCondition = this.IsSilverlightInitializerRequired ? CompilationSymbol.NotSilverlight.Append( this.Condition ) : CompilationSymbol.None;
                yield return new InitializationMember( this.DependencyPropertyKeyFieldName, w => this.WriteNewDependencyPropertyInitializer( w, wpfArgs ) ) {
                    MemberScope = initializerScope,
                    Condition = wpfCondition,
                    ReferencedExtensions = wpfArgs.UsedExtensions,
                    DependentInitializer = this.IsReadOnly
                        ? new InitializationMember( this.FieldName, this.DependencyPropertyKeyFieldName + "." + this.FieldTypeName ) { MemberScope = initializerScope, Condition = wpfCondition }
                        : null
                };

                var silverlightArgs = this.BuildRegistrationArguments( true );
                if( this.IsSilverlightInitializerRequired )
                    yield return new InitializationMember( this.DependencyPropertyKeyFieldName, w => this.WriteNewDependencyPropertyInitializer( w, silverlightArgs ) ) {
                        MemberScope = initializerScope,
                        Condition = CompilationSymbol.Silverlight.Append( this.Condition ),
                        ReferencedExtensions = silverlightArgs.UsedExtensions,
                        DependentInitializer = this.IsReadOnly
                            ? new InitializationMember( this.FieldName, this.DependencyPropertyKeyFieldName ) { MemberScope = initializerScope, Condition = CompilationSymbol.Silverlight }
                            : null
                    };
            }
        }


        /// <inheritdoc/>
        public NewDependencyProperty( PartialType parent, string name, string description )
            : base( parent, name, description ) { }


        private void WriteNewDependencyPropertyInitializer( ICodeWriter writer, DependencyPropertyMetadata args ) {
            string registerAttached = this.Attached ? "Attached" : "";
            string registerReadOnly = !args.Silverlight && this.IsReadOnly ? "ReadOnly" : "";

            writer.Write( "{0}.Register{1}{2}", this.FieldTypeName, registerAttached, registerReadOnly );
            using( Enclose.Parenthesis( writer ) )
            using( Enclose.NewLine( writer ) )
            using( Enclose.Indent( writer ) ) {
                writer.WriteLine( "\"{0}\", typeof({1}), typeof({2}),", this.AccessorName, this.TypeName, this.Parent.TypeName );
                args.Write( writer );
            }
        }

    }

}
